#include "tcp_client.h"
#include "app_control.h"
#include "stdio.h"
#if CLIENT_SELECT == NETCONN
#include "lwip/opt.h"
#include "lwip/sys.h"
#include "lwip/api.h"

static void client(void *thread_param)
{
	struct netconn *conn;
	int ret;
	ip4_addr_t ipaddr;
	uint8_t send_buf[]= "This is a TCP Client test...\n";
	while (1)
	{
		conn = netconn_new(NETCONN_TCP);
		//调用 netconn_new()函数申请一个连接结构，指定参数是NETCONN_TCP，
		//即 TCP 连接， 在这里将初始化 netconn 连接结构的相关参数，
		//但并不会产生连接，返回指向连接结构的指针并且保存在 conn 中。
		if (conn == NULL)
		{
			printf("create conn failed!\r\n");
			vTaskDelay(10);
			continue;
		}
		IP4_ADDR(&ipaddr,192,168,1,225);//配置服务器的 IP 地址。
		ret = netconn_connect(conn,&ipaddr,5001);//调用 netconn_connect()函数连接服务器，指定端口为 5001。
		if (ret == -1)
		{
			printf("Connect failed!\r\n");
			netconn_close(conn);//如果连接失败就删除 conn 连接结构，然后尝试重连。
			vTaskDelay(10);
			continue;
		}
		printf("Connect to iperf server successful!\r\n");
		while (1)
		{
			//连接成功后，每隔1秒调用netconn_write()函数发送数据到服务器中。
			ret = netconn_write(conn,send_buf,sizeof(send_buf),0);
			vTaskDelay(1000);
		}
	}
}

void client_init(void)
{
	sys_thread_new("client", client, NULL, 512, 4);
}

#elif CLIENT_SELECT == Socket
#include "lwip/opt.h"
#include "lwip/sys.h"
#include "lwip/api.h"
#include <lwip/sockets.h>
#define PORT 5001
#define IP_ADDR "192.168.1.225"
static void client(void *thread_param)
{
	int sock = -1;
	struct sockaddr_in client_addr;
	uint8_t send_buf[]= "This is a TCP Client test...\n";
	while (1)
	{
		sock = socket(AF_INET, SOCK_STREAM, 0);
		if (sock < 0)
		{
			printf("Socket error\r\n");
			vTaskDelay(10);
			continue;
		}
		client_addr.sin_family = AF_INET;
		client_addr.sin_port = htons(PORT);
		client_addr.sin_addr.s_addr = inet_addr(IP_ADDR);
		memset(&(client_addr.sin_zero), 0, sizeof(client_addr.sin_zero));
		if (connect(sock,(struct sockaddr *)&client_addr,sizeof(struct sockaddr)) == -1)
		{
			printf("Connect failed!\r\n");
			closesocket(sock);
			vTaskDelay(10);
			continue;
		}
		printf("Connect to iperf server successful!\r\n");
		while (1)
		{
			if(write(sock,send_buf,sizeof(send_buf)) < 0)
				break;
			vTaskDelay(1000);
		}
		closesocket(sock);
	}
}

void client_init(void)
{
	sys_thread_new("client", client, NULL, 512, 4);
}

#elif CLIENT_SELECT == RAW_API
#include "lwip/netif.h"
#include "lwip/ip.h"
#include "lwip/tcp.h"
#include "lwip/init.h"
#include "netif/etharp.h"
#include "lwip/udp.h"
#include "lwip/pbuf.h"
#include <string.h>

#define TCP_CLIENT_PORT 5001

static struct tcp_pcb *client_pcb = NULL;
void TCP_Client_Init(void);

static void client_err(void *arg, err_t err)
{
	printf("connect error! closed by core!!\r\n");
	printf("try to connect to server again!!\r\n");
	//连接失败的时候释放 TCP 控制块的内存
	tcp_close(client_pcb);
	//重新连接
	TCP_Client_Init();
}

static err_t client_send(void *arg, struct tcp_pcb *tpcb)
{
	uint8_t send_buf[]= "This is a TCP Client test...\n";
	//发送数据到服务器LwIP
	tcp_write(tpcb, send_buf, sizeof(send_buf), 1);
	return ERR_OK;
}

static err_t client_recv(void *arg,struct tcp_pcb *tpcb,struct pbuf *p,err_t err)
{
	if(p != NULL)
	{
		/* 更新窗口 */
		tcp_recved(tpcb, p->tot_len);
		/* 返回接收到的数据*/
		tcp_write(tpcb, p->payload, p->tot_len, 1);
		memset(p->payload, 0 , p->tot_len);
		pbuf_free(p);
	}
	else if(err == ERR_OK)
	{
		//服务器断开连接
		printf("server has been disconnected!\r\n");
		tcp_close(tpcb);
		//重新连接
		TCP_Client_Init();
	}
	return ERR_OK;
}

static err_t client_connected(void *arg,struct tcp_pcb *pcb,err_t err)
{
	printf("connected ok!\r\n");
	//注册一个周期性回调函数
	tcp_poll(pcb,client_send,2);
	//注册一个接收函数
	tcp_recv(pcb,client_recv);
	return ERR_OK;
}

static void TCP_Client_Init(void)
{
	ip4_addr_t server_ip;
	/* 创建一个 TCP 控制块 */
	client_pcb = tcp_new();
	IP4_ADDR(&server_ip, 192,168,1,225);
	printf("client start connect!\r\n");
	//开始连接
	tcp_connect(client_pcb,&server_ip,TCP_CLIENT_PORT,client_connected);
	//注册异常处理LwIP
	tcp_err(client_pcb, client_err);
}

void client_init(void)
{
	TCP_Client_Init();
}

#else
void client_init(void)
{
	
}

#endif
